import { VTActor, VTActorRenderType } from "./VTActor.ts";
import vtkPolyData from "@kitware/vtk.js/Common/DataModel/PolyData";
import { BdfLoader } from "../IO/BdfLoader.ts";
import vtkPoints from "@kitware/vtk.js/Common/Core/Points";
import vtkCellArray from "@kitware/vtk.js/Common/Core/CellArray";
import vtkDataArray from "@kitware/vtk.js/Common/Core/DataArray";
import vtkLookupTable from "@kitware/vtk.js/Common/Core/LookupTable";
import { ColorMode } from "@kitware/vtk.js/Rendering/Core/Mapper/Constants";
import vtkScalarBarActor from "@kitware/vtk.js/Rendering/Core/ScalarBarActor";
import { CompLabel } from "../Components/CompLabel.ts";
import { devtool } from "../devtool.ts";
import { STLabel, STAxis, AdvanceSTActor } from "../types/index.ts";

// 🧮工具函数 生成彩虹色数组
export function generateRainbowColors(numColors = 256) {
  const colors = [];
  for (let i = 0; i < numColors; i++) {
    const t = i / (numColors - 1); // 归一化到 [0, 1]
    let r, g, b;

    if (t < 0.25) {
      // 蓝色到青色
      r = 0;
      g = (t / 0.25) * 255;
      b = 255;
    } else if (t < 0.5) {
      // 青色到绿色
      r = 0;
      g = 255;
      b = 255 - ((t - 0.25) / 0.25) * 255;
    } else if (t < 0.75) {
      // 绿色到黄色
      r = ((t - 0.5) / 0.25) * 255;
      g = 255;
      b = 0;
    } else {
      // 黄色到红色
      r = 255;
      g = 255 - ((t - 0.75) / 0.25) * 255;
      b = 0;
    }
    colors.push([r, g, b, 255]); // 添加 RGB 和透明度 A
  }
  return colors;
}

const rainbow = generateRainbowColors(256);

export enum StandardType {
  VEC1 = "vec1",
  VEC3 = "vec3",
  DIFF = "diff",
}

export interface StandardData {
  name: string;
  type: StandardType;
  eid?: number[];
  value: any;
  label?: STLabel[];
  scalarBarTitle?: string;
  axis?: STAxis;
}

export interface PolyDataModel {
  points: vtkPoints;
  cells: vtkCellArray;
}

export function refactorPolyData(
  eid_array: number[],
  loader: BdfLoader
): PolyDataModel {
  let tmp_nodes_array: number[] = [];
  let ids_arr_arr: number[][] = [];
  // ➡️ 偏移量用来处理 重建cell
  let offset = 0;
  eid_array.forEach((eid) => {
    // 1️⃣ 从表中查询单元索引
    const cellIdx = loader.elementsIdIndexMap[eid];
    // 2️⃣ 获取单元顶点索引数据
    const pointIdxArr = loader.cellsIdIndexMap[cellIdx];
    const count = pointIdxArr.length;
    let cellIndexArr = [];
    for (let i = 0; i < count; i++) {
      cellIndexArr.push(offset);
      offset++;
    }
    ids_arr_arr.push(cellIndexArr);
    // 3️⃣ 获取索引对应的顶点坐标
    pointIdxArr.forEach((pntIdx: number) => {
      tmp_nodes_array.push(
        loader.origin.nodes[3 * pntIdx],
        loader.origin.nodes[3 * pntIdx + 1],
        loader.origin.nodes[3 * pntIdx + 2]
      );
    });
  });
  return {
    points: refactorPointData(tmp_nodes_array),
    cells: refactorCellData(ids_arr_arr),
  };
}

export function refactorPointData(pntsArr: number[]) {
  const points = vtkPoints.newInstance();
  const TMP_arr = new Float32Array(pntsArr.length).fill(0.0);
  pntsArr.map((v: any, index: number) => {
    TMP_arr[index] = Number(v);
  });
  points.setData(TMP_arr, 3);
  return points;
}

function refactorCellData(ids_arr_arr: number[][]) {
  const cells = vtkCellArray.newInstance();
  for (let i = 0; i < ids_arr_arr.length; i++) {
    cells.insertNextCell(ids_arr_arr[i]);
  }
  return cells;
}

export interface ActorComponent {
  scalarBar: {
    isCreated: boolean;
    instance: vtkScalarBarActor | null;
    isShow: boolean;
  };
}

/**
 * ➡️ 后处理标准数据渲染actor
 */
@CompLabel
export class STActor extends VTActor {
  readonly standardData: StandardData;
  // 🫐 用于区分diff 不同区段的偏移位置
  diffOffset: number[] = [];
  // ☀️ 标尺范围
  scalarRange: number[] = [];
  lut: vtkLookupTable | null = null;

  components: ActorComponent = {
    scalarBar: {
      isCreated: false,
      instance: null,
      isShow: false,
    },
  };

  constructor(standardData: StandardData, loader: BdfLoader) {
    let poly = vtkPolyData.newInstance();
    let eids: any = [];
    let diffOffset: number[] = [];
    if (standardData.type === StandardType.VEC1) {
      eids = standardData.eid ?? [];
    } else if (standardData.type === StandardType.DIFF) {
      // ➡️ 读取diff数据 合并eid
      const keys = Object.keys(standardData.value);
      keys.forEach((key: string) => {
        eids = eids.concat(standardData.value[key]);
        // ➡️ 标记分割位置
        diffOffset.push(eids.length);
      });
    }
    const { points, cells } = refactorPolyData(eids, loader);
    poly.setPoints(points);
    poly.setPolys(cells);
    super(poly);
    this.standardData = standardData;
    this.diffOffset = diffOffset;
    this.which(
      () => {
        this.rebuildLut();
      },
      () => {
        this.rebuildDiffColor(eids.length);
      },
      () => {}
    );
    this.setRenderType(VTActorRenderType.SURFACE_WITH_EDGE);
    // @ 处理标尺标题 📏
    if (this.standardData.scalarBarTitle) {
      this.createScalarBar();
      this.setScalarBarTitle(this.standardData.scalarBarTitle);
      this.showScalarBar();
    }
  }

  // ➡️ 重建颜色映射
  rebuildLut() {
    if (this.standardData.type === StandardType.VEC1) {
      const size: number = this.standardData.eid?.length || 0;
      if (size === 0) {
        devtool.error("eid是空的");
        return;
      }
      const scalars = vtkDataArray.newInstance({ size: size });
      for (let i = 0; i < size; i++) {
        scalars.setTuple(i, [this.standardData.value[i]]);
      }
      const lut = vtkLookupTable.newInstance({
        numberOfColors: 256,
      });
      lut.setTable(rainbow);
      lut.build();
      this.lut = lut;
      const range = scalars.getRange();
      this.scalarRange = range;
      lut.setRange(range[0], range[1]);
      const color: any = (lut as any).mapScalars(
        scalars,
        ColorMode.MAP_SCALARS,
        0
      );
      const colors = color.getTuples();
      for (let i = 0; i < size; i++) {
        if (this.standardData.value[i] < 0) {
          this.setCellsColor([i], [0, 0, 0, 255]);
        } else {
          this.setCellsColor(
            [i],
            [
              colors[4 * i],
              colors[4 * i + 1],
              colors[4 * i + 2],
              colors[4 * i + 3],
            ]
          );
        }
      }
    }
  }

  // ➡️ diff类型的颜色重建
  rebuildDiffColor(len: number) {
    const colorMap = [
      [10, 10, 10, 150],
      [255, 0, 0, 255],
    ];
    for (let i = 0; i < len; i++) {
      let seg = 0;

      for (let j = 0; j < this.diffOffset.length; j++) {
        if (i < this.diffOffset[j]) {
          seg = j;
          break;
        }
      }
      this.setCellsColor([i], colorMap[seg]);
    }
  }

  private which(a: () => void, b: () => void, c: () => void) {
    switch (this.standardData.type) {
      case StandardType.VEC1:
        a && a();
        break;
      case StandardType.DIFF:
        b && b();
        break;
      case StandardType.VEC3:
        c && c();
        break;
    }
  }

  createScalarBar() {
    if (!this.lut) return;
    this.mapper.setLookupTable(this.lut);
    this.mapper.setScalarVisibility(true);
    this.mapper.setScalarRange(this.scalarRange[0], this.scalarRange[1]);
    this.mapper.modified();
    const scalarBarActor = vtkScalarBarActor.newInstance({
      automated: true,
      drawNanAnnotation: false,
    });
    scalarBarActor.setScalarsToColors(this.lut);
    scalarBarActor.setAxisTextStyle({
      fontColor: "black",
    });
    scalarBarActor.setTickTextStyle({
      fontColor: "black",
    });
    this.components.scalarBar.instance = scalarBarActor;
    this.components.scalarBar.isCreated = true;
    return scalarBarActor;
  }

  showScalarBar() {
    if (!this.components.scalarBar.isCreated) {
      this.createScalarBar();
    }
    // * 防御性
    if (!this.components.scalarBar.instance) {
      return;
    }
    this.components.scalarBar.isShow = true;
  }

  hideScalarBar() {
    this.components.scalarBar.isShow = false;
  }

  // * 设置标尺title
  setScalarBarTitle(title: string) {
    this.components.scalarBar.instance?.setAxisLabel(title);
  }
}
